namespace HexLib
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Windows.Forms;

    public class DayView : Control
    {
        private ITool activeTool;
        private int allDayEventsHeaderHeight = 20;
        private bool allowInplaceEditing = true;
        private bool allowNew = true;
        private bool allowScroll = true;
        private bool ampmdisplay;
        private AppHeightDrawMode appHeightMode;
        private int appointmentGripWidth = 5;
        internal Dictionary<Appointment, AppointmentView> appointmentViews = new Dictionary<Appointment, AppointmentView>();
        private Hashtable cachedAppointments = new Hashtable();
        private int dayHeadersHeight = 20;
        private int daysToShow = 1;
        private bool drawAllAppBorder;
        private DrawTool drawTool;
        private TextBox editbox;
        private int halfHourHeight = 0x12;
        private int horizontalAppointmentHeight = 20;
        private int hourLabelIndent = 2;
        private int hourLabelWidth = 50;
        internal Dictionary<Appointment, AppointmentView> longappointmentViews = new Dictionary<Appointment, AppointmentView>();
        private bool minHalfHourApp;
        private AbstractRenderer renderer;
        private VScrollBar scrollbar;
        private Appointment selectedAppointment;
        private bool selectedAppointmentIsNew;
        private SelectionType selection;
        private DateTime selectionEnd;
        private DateTime selectionStart;
        private SelectionTool selectionTool;
        private DateTime startDate;
        private int startHour = 8;
        private DateTime workEnd;
        private int workingHourEnd = 0x12;
        private int workingHourStart = 8;
        private int workingMinuteEnd = 30;
        private int workingMinuteStart = 30;
        private DateTime workStart;
        private int numberWorkingDay = 7;

        public event EventHandler<AppointmentEventArgs> AppointmentMove;

        public event NewAppointmentEventHandler NewAppointment;

        public event ResolveAppointmentsEventHandler ResolveAppointments;

        public event EventHandler SelectionChanged;

        public DayView()
        {
            base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            base.SetStyle(ControlStyles.ResizeRedraw, true);
            base.SetStyle(ControlStyles.Selectable, true);
            this.scrollbar = new VScrollBar();
            this.scrollbar.SmallChange = this.halfHourHeight;
            this.scrollbar.LargeChange = this.halfHourHeight * 2;
            this.scrollbar.Dock = DockStyle.Right;
            this.scrollbar.Visible = this.allowScroll;
            this.scrollbar.Scroll += new ScrollEventHandler(this.scrollbar_Scroll);
            this.AdjustScrollbar();
            this.scrollbar.Value = (this.startHour * 2) * this.halfHourHeight;
            base.Controls.Add(this.scrollbar);
            this.editbox = new TextBox();
            this.editbox.Multiline = true;
            this.editbox.Visible = false;
            this.editbox.BorderStyle = BorderStyle.None;
            this.editbox.KeyUp += new KeyEventHandler(this.editbox_KeyUp);
            this.editbox.Margin = Padding.Empty;
            base.Controls.Add(this.editbox);
            this.drawTool = new DrawTool();
            this.drawTool.DayView = this;
            this.selectionTool = new SelectionTool();
            this.selectionTool.DayView = this;
            this.selectionTool.Complete += new EventHandler(this.selectionTool_Complete);
            this.activeTool = this.drawTool;
            this.UpdateWorkingHours();
            this.Renderer = new Office12Renderer();
        }

        private void AdjustScrollbar()
        {
            this.scrollbar.Maximum = (((2 * this.halfHourHeight) * 0x19) - base.Height) + this.HeaderHeight;
            this.scrollbar.Minimum = 0;
        }

        private void DrawAppointments(PaintEventArgs e, Rectangle rect, DateTime time, string group)
        {
            DateTime time3 = time.Date.AddHours(24).AddSeconds(-1);
            AppointmentList appointments = (AppointmentList) this.cachedAppointments[time.Day];
            if (appointments != null)
            {
                HalfHourLayout[] maxParalelAppointments = GetMaxParalelAppointments(appointments);
                List<Appointment> list2 = new List<Appointment>();
                for (int i = 0; i < 0x30; i++)
                {
                    HalfHourLayout layout = maxParalelAppointments[i];
                    if ((layout != null) && (layout.Count > 0))
                    {
                        for (int j = 0; j < layout.Count; j++)
                        {
                            Appointment item = layout.Appointments[j];
                            if ((item.Group == group) && (list2.IndexOf(item) < 0))
                            {
                                AppointmentView view;
                                Rectangle baseRectangle = rect;
                                int num3 = rect.Width / item.conflictCount;
                                int x = 0;
                                foreach (Appointment appointment2 in layout.Appointments)
                                {
                                    if (((appointment2 != null) && (appointment2.Group == item.Group)) && this.appointmentViews.ContainsKey(appointment2))
                                    {
                                        view = this.appointmentViews[appointment2];
                                        if (x < view.Rectangle.X)
                                        {
                                            x = view.Rectangle.X;
                                        }
                                    }
                                }
                                if ((x + (num3 * 2)) > (rect.X + rect.Width))
                                {
                                    x = 0;
                                }
                                baseRectangle.Width = num3 - 5;
                                if (x > 0)
                                {
                                    baseRectangle.X = x + num3;
                                }
                                DateTime start = item.StartDate;
                                DateTime end = item.EndDate;
                                if ((this.AppHeightMode == AppHeightDrawMode.FullHalfHourBlocksShort) && (item.EndDate.Subtract(item.StartDate).TotalMinutes < 30))
                                {
                                    start = item.StartDate.AddMinutes((double) -item.StartDate.Minute);
                                    end = item.EndDate.AddMinutes((double) (30 - item.EndDate.Minute));
                                    if (item.StartDate.Minute >= 30)
                                    {
                                        start = start.AddMinutes(30);
                                    }
                                    if (item.EndDate.Minute > 30)
                                    {
                                        end = end.AddMinutes(30);
                                    }
                                }
                                else if (this.AppHeightMode == AppHeightDrawMode.FullHalfHourBlocksAll)
                                {
                                    start = item.StartDate.AddMinutes((double) -item.StartDate.Minute);
                                    if ((item.EndDate.Minute != 0) && (item.EndDate.Minute != 30))
                                    {
                                        end = item.EndDate.AddMinutes((double) (30 - item.EndDate.Minute));
                                    }
                                    else
                                    {
                                        end = item.EndDate;
                                    }
                                    if (item.StartDate.Minute >= 30)
                                    {
                                        start = start.AddMinutes(30);
                                    }
                                    if (item.EndDate.Minute > 30)
                                    {
                                        end = end.AddMinutes(30);
                                    }
                                }
                                else if ((this.AppHeightMode == AppHeightDrawMode.EndHalfHourBlocksShort) && (item.EndDate.Subtract(item.StartDate).TotalMinutes < 30))
                                {
                                    end = item.EndDate.AddMinutes((double) (30 - item.EndDate.Minute));
                                    if (item.EndDate.Minute > 30)
                                    {
                                        end = end.AddMinutes(30);
                                    }
                                }
                                else if (this.AppHeightMode == AppHeightDrawMode.EndHalfHourBlocksAll)
                                {
                                    if ((item.EndDate.Minute != 0) && (item.EndDate.Minute != 30))
                                    {
                                        end = item.EndDate.AddMinutes((double) (30 - item.EndDate.Minute));
                                    }
                                    else
                                    {
                                        end = item.EndDate;
                                    }
                                    if (item.EndDate.Minute > 30)
                                    {
                                        end = end.AddMinutes(30);
                                    }
                                }
                                baseRectangle = this.GetHourRangeRectangle(start, end, baseRectangle);
                                view = new AppointmentView();
                                view.Rectangle = baseRectangle;
                                view.Appointment = item;
                                this.appointmentViews[item] = view;
                                e.Graphics.SetClip(rect);
                                if (this.DrawAllAppBorder)
                                {
                                    item.DrawBorder = true;
                                }
                                Rectangle gripRect = this.GetHourRangeRectangle(item.StartDate, item.EndDate, baseRectangle);
                                gripRect.Width = this.appointmentGripWidth;
                                this.renderer.DrawAppointment(e.Graphics, baseRectangle, item, item == this.selectedAppointment, gripRect);
                                e.Graphics.ResetClip();
                                list2.Add(item);
                            }
                        }
                    }
                }
            }
        }

        private void DrawDay(PaintEventArgs e, Rectangle rect, DateTime time)
        {
            Rectangle rectangle = this.GetHourRangeRectangle(this.workStart, this.workEnd, rect);
            if (rectangle.Y < this.HeaderHeight)
            {
                rectangle.Height -= this.HeaderHeight - rectangle.Y;
                rectangle.Y = this.HeaderHeight;
            }

            if( (NumberWorkingDay == 7) ||
                ((NumberWorkingDay == 6) && (time.DayOfWeek != DayOfWeek.Sunday)) ||
                ((NumberWorkingDay == 5) && ( (time.DayOfWeek != DayOfWeek.Sunday) &&(time.DayOfWeek != DayOfWeek.Saturday))))
            {
                this.renderer.DrawHourRange(e.Graphics, rectangle, false, false);
            }
            if ((this.selection == SelectionType.DateRange) && (time.Day == this.selectionStart.Day))
            {
                Rectangle rectangle2 = this.GetHourRangeRectangle(this.selectionStart, this.selectionEnd, rect);
                if ((rectangle2.Top + 1) > this.HeaderHeight)
                {
                    this.renderer.DrawHourRange(e.Graphics, rectangle2, false, true);
                }
            }
            e.Graphics.SetClip(rect);
            for (int i = 0; i < 0x30; i++)
            {
                int num2 = (rect.Top + (i * this.halfHourHeight)) - this.scrollbar.Value;
                using (Pen pen = new Pen(((i % 2) == 0) ? this.renderer.HourSeperatorColor : this.renderer.HalfHourSeperatorColor))
                {
                    e.Graphics.DrawLine(pen, rect.Left, num2, rect.Right, num2);
                }
                if (num2 > rect.Bottom)
                {
                    break;
                }
            }
            this.renderer.DrawDayGripper(e.Graphics, rect, this.appointmentGripWidth);
            e.Graphics.ResetClip();
            AppointmentList list = (AppointmentList) this.cachedAppointments[time.Day];
            if (list != null)
            {
                List<string> list2 = new List<string>();
                foreach (Appointment appointment in list)
                {
                    if (!list2.Contains(appointment.Group))
                    {
                        list2.Add(appointment.Group);
                    }
                }
                Rectangle rectangle3 = rect;
                rectangle3.Width /= list2.Count;
                list2.Sort();
                foreach (string text in list2)
                {
                    this.DrawAppointments(e, rectangle3, time, text);
                    rectangle3.X += rectangle3.Width;
                }
            }
        }

        private void DrawDayHeaders(PaintEventArgs e, Rectangle rect)
        {
            int width = rect.Width / this.daysToShow;
            Rectangle rectangle = new Rectangle(rect.Left, rect.Top, width, rect.Height);
            DateTime date = this.startDate;
            for (int i = 0; i < this.daysToShow; i++)
            {
                this.renderer.DrawDayHeader(e.Graphics, rectangle, date);
                rectangle.X += width;
                date = date.AddDays(1);
            }
        }

        private void DrawDays(PaintEventArgs e, Rectangle rect)
        {
            int num = rect.Width / this.daysToShow;
            AppointmentList list = (AppointmentList) this.cachedAppointments[-1];
            AppointmentList list2 = new AppointmentList();
            int dayHeadersHeight = this.dayHeadersHeight;
            bool flag = false;
            List<int> list3 = new List<int>();
            if (list != null)
            {
                foreach (Appointment appointment in list)
                {
                    appointment.Layer = 0;
                    if (list2.Count == 0)
                    {
                        goto Label_0198;
                    }
                    foreach (Appointment appointment2 in list2)
                    {
                        if (!list3.Contains(appointment2.Layer))
                        {
                            list3.Add(appointment2.Layer);
                        }
                    }
                    foreach (int num3 in list3)
                    {
                        foreach (Appointment appointment3 in list2)
                        {
                            if (appointment3.Layer == num3)
                            {
                                if ((appointment.StartDate.Date >= appointment3.EndDate.Date) || (appointment.EndDate.Date <= appointment3.StartDate.Date))
                                {
                                    flag = false;
                                }
                                else
                                {
                                    flag = true;
                                    goto Label_0166;
                                }
                            }
                            appointment.Layer = num3;
                        }
                    Label_0166:
                        if (!flag)
                        {
                            goto Label_0186;
                        }
                    }
                Label_0186:
                    if (flag)
                    {
                        appointment.Layer = list3.Count;
                    }
                Label_0198:
                    list2.Add(appointment);
                }
                foreach (Appointment appointment4 in list2)
                {
                    if (!list3.Contains(appointment4.Layer))
                    {
                        list3.Add(appointment4.Layer);
                    }
                }
                this.allDayEventsHeaderHeight = (list3.Count * (this.horizontalAppointmentHeight + 5)) + 5;
                Rectangle rectangle = rect;
                rectangle.Y = dayHeadersHeight;
                rectangle.Height = this.allDayEventsHeaderHeight;
                this.renderer.DrawAllDayBackground(e.Graphics, rectangle);
                foreach (Appointment appointment5 in list)
                {
                    Rectangle rectangle2 = rect;
                    int days = appointment5.EndDate.Subtract(appointment5.StartDate).Days;
                    if ((appointment5.EndDate.Day != appointment5.StartDate.Day) && (appointment5.EndDate.TimeOfDay < appointment5.StartDate.TimeOfDay))
                    {
                        days++;
                    }
                    rectangle2.Width = (num * days) - 5;
                    rectangle2.Height = this.horizontalAppointmentHeight;
                    rectangle2.X += appointment5.StartDate.Subtract(this.startDate).Days * num;
                    rectangle2.Y = (dayHeadersHeight + (appointment5.Layer * (this.horizontalAppointmentHeight + 5))) + 5;
                    AppointmentView view = new AppointmentView();
                    view.Rectangle = rectangle2;
                    view.Appointment = appointment5;
                    this.longappointmentViews[appointment5] = view;
                    Rectangle gripRect = rectangle2;
                    gripRect.Width = this.appointmentGripWidth;
                    this.renderer.DrawAppointment(e.Graphics, rectangle2, appointment5, appointment5 == this.selectedAppointment, gripRect);
                }
            }
            DateTime startDate = this.startDate;
            Rectangle rectangle4 = rect;
            rectangle4.Width = num;
            rectangle4.Y += this.allDayEventsHeaderHeight;
            rectangle4.Height -= this.allDayEventsHeaderHeight;
            this.appointmentViews.Clear();
            list3.Clear();
            for (int i = 0; i < this.daysToShow; i++)
            {
                this.DrawDay(e, rectangle4, startDate);
                rectangle4.X += num;
                startDate = startDate.AddDays(1);
            }
        }

        private void DrawHourLabels(PaintEventArgs e, Rectangle rect)
        {
            e.Graphics.SetClip(rect);
            for (int i = 0; i < 0x18; i++)
            {
                Rectangle rectangle = rect;
                rectangle.Y = (rect.Y + ((i * 2) * this.halfHourHeight)) - this.scrollbar.Value;
                rectangle.X += this.hourLabelIndent;
                rectangle.Width = this.hourLabelWidth;
                if (rectangle.Y > (this.HeaderHeight / 2))
                {
                    this.renderer.DrawHourLabel(e.Graphics, rectangle, i, this.AmPmDisplay);
                }
            }
            e.Graphics.ResetClip();
        }

        private void editbox_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                e.Handled = true;
                this.FinishEditing(true);
            }
            else if (e.KeyCode == Keys.Return)
            {
                e.Handled = true;
                this.FinishEditing(false);
            }
        }

        private void EnterEditMode(object state)
        {
            if (this.allowInplaceEditing)
            {
                if (base.InvokeRequired)
                {
                    Appointment selectedAppointment = this.selectedAppointment;
                    Thread.Sleep(200);
                    if (selectedAppointment == this.selectedAppointment)
                    {
                        base.Invoke(new StartEditModeDelegate(this.EnterEditMode), new object[] { state });
                    }
                }
                else
                {
                    this.StartEditing();
                }
            }
        }

        private void EnterNewAppointmentMode(char key)
        {
            Appointment appointment = new Appointment();
            appointment.StartDate = this.selectionStart;
            appointment.EndDate = this.selectionEnd;
            appointment.Title = key.ToString();
            this.selectedAppointment = appointment;
            this.selectedAppointmentIsNew = true;
            this.activeTool = this.selectionTool;
            base.Invalidate();
            ThreadPool.QueueUserWorkItem(new WaitCallback(this.EnterEditMode));
        }

        public void FinishEditing(bool cancel)
        {
            this.editbox.Visible = false;
            if (!cancel)
            {
                if (this.selectedAppointment != null)
                {
                    this.selectedAppointment.Title = this.editbox.Text;
                }
            }
            else if (this.selectedAppointmentIsNew)
            {
                this.selectedAppointment = null;
                this.selectedAppointmentIsNew = false;
            }
            base.Invalidate();
            base.Focus();
        }

        public Appointment GetAppointmentAt(int x, int y)
        {
            foreach (AppointmentView view in this.appointmentViews.Values)
            {
                if (view.Rectangle.Contains(x, y))
                {
                    return view.Appointment;
                }
            }
            foreach (AppointmentView view2 in this.longappointmentViews.Values)
            {
                if (view2.Rectangle.Contains(x, y))
                {
                    return view2.Appointment;
                }
            }
            return null;
        }

        public Rectangle GetFullDayApptsRectangle()
        {
            Rectangle clientRectangle = base.ClientRectangle;
            clientRectangle.Height = this.HeaderHeight - this.dayHeadersHeight;
            clientRectangle.Y += this.dayHeadersHeight;
            clientRectangle.Width -= (this.hourLabelWidth + this.hourLabelIndent) + this.scrollbar.Width;
            clientRectangle.X += this.hourLabelWidth + this.hourLabelIndent;
            return clientRectangle;
        }

        private Rectangle GetHourRangeRectangle(DateTime start, DateTime end, Rectangle baseRectangle)
        {
            Rectangle rectangle = baseRectangle;
            int num = ((start.Hour * this.halfHourHeight) * 2) + ((start.Minute * this.halfHourHeight) / 30);
            int num2 = ((end.Hour * this.halfHourHeight) * 2) + ((end.Minute * this.halfHourHeight) / 30);
            rectangle.Y = (num - this.scrollbar.Value) + this.HeaderHeight;
            rectangle.Height = Math.Max(1, num2 - num);
            return rectangle;
        }

        private static HalfHourLayout[] GetMaxParalelAppointments(List<Appointment> appointments)
        {
            HalfHourLayout[] layoutArray = new HalfHourLayout[0x30];
            foreach (Appointment appointment in appointments)
            {
                appointment.conflictCount = 1;
            }
            foreach (Appointment appointment2 in appointments)
            {
                int num = (appointment2.StartDate.Hour * 2) + (appointment2.StartDate.Minute / 30);
                int num2 = (appointment2.EndDate.Hour * 2) + (appointment2.EndDate.Minute / 30);
                if (num2 == num)
                {
                    if (num2 < 0x30)
                    {
                        num2++;
                    }
                    else
                    {
                        num--;
                    }
                }
                for (int i = num; i < num2; i++)
                {
                    HalfHourLayout layout = layoutArray[i];
                    if (layout == null)
                    {
                        layout = new HalfHourLayout();
                        layout.Appointments = new Appointment[20];
                        layoutArray[i] = layout;
                    }
                    layout.Appointments[layout.Count] = appointment2;
                    layout.Count++;
                    List<string> list = new List<string>();
                    foreach (Appointment appointment3 in layout.Appointments)
                    {
                        if ((appointment3 != null) && !list.Contains(appointment3.Group))
                        {
                            list.Add(appointment3.Group);
                        }
                    }
                    layout.Groups = list;
                    foreach (Appointment appointment4 in layout.Appointments)
                    {
                        if (((appointment4 != null) && (appointment4.Group == appointment2.Group)) && (appointment4.conflictCount < layout.Count))
                        {
                            appointment4.conflictCount = layout.Count - (layout.Groups.Count - 1);
                        }
                    }
                }
            }
            return layoutArray;
        }

        public DateTime GetTimeAt(int x, int y)
        {
            int num = (base.Width - ((this.scrollbar.Width + this.hourLabelWidth) + this.hourLabelIndent)) / this.daysToShow;
            int num2 = ((y - this.HeaderHeight) + this.scrollbar.Value) / this.halfHourHeight;
            x -= this.hourLabelWidth;
            DateTime time = this.startDate.Date.AddDays((double) (x / num));
            if ((num2 > 0) && (num2 < 0x30))
            {
                time = time.AddMinutes((double) (num2 * 30));
            }
            return time;
        }

        public Rectangle GetTrueRectangle()
        {
            Rectangle clientRectangle = base.ClientRectangle;
            clientRectangle.X += this.hourLabelWidth + this.hourLabelIndent;
            clientRectangle.Width -= (this.scrollbar.Width + this.hourLabelWidth) + this.hourLabelIndent;
            clientRectangle.Y += this.HeaderHeight;
            clientRectangle.Height -= this.HeaderHeight;
            return clientRectangle;
        }

        private void OnAllowScrollChanged()
        {
            this.scrollbar.Visible = this.AllowScroll;
        }

        private void OnAmPmDisplayChanged()
        {
            base.Invalidate();
        }

        protected virtual void OnDaysToShowChanged()
        {
            if (this.CurrentlyEditing)
            {
                this.FinishEditing(true);
            }
            base.Invalidate();
        }

        private void OnDrawAllAppBorderChanged()
        {
            base.Invalidate();
        }

        private void OnHalfHourHeightChanged()
        {
            this.AdjustScrollbar();
            base.Invalidate();
        }

        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            if ((this.allowNew && char.IsLetterOrDigit(e.KeyChar)) && ((this.Selection == SelectionType.DateRange) && !this.selectedAppointmentIsNew))
            {
                this.EnterNewAppointmentMode(e.KeyChar);
            }
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.Focus();
            if (this.CurrentlyEditing)
            {
                this.FinishEditing(false);
            }
            if (this.selectedAppointmentIsNew)
            {
                this.RaiseNewAppointment();
            }
            ITool drawTool = null;
            Appointment appointmentAt = this.GetAppointmentAt(e.X, e.Y);
            if (((e.Y < this.HeaderHeight) && (e.Y > this.dayHeadersHeight)) && (appointmentAt == null))
            {
                if (this.selectedAppointment != null)
                {
                    this.selectedAppointment = null;
                    base.Invalidate();
                }
                drawTool = this.drawTool;
                this.selection = SelectionType.None;
                base.OnMouseDown(e);
            }
            else
            {
                if (appointmentAt == null)
                {
                    if (this.selectedAppointment != null)
                    {
                        this.selectedAppointment = null;
                        base.Invalidate();
                    }
                    drawTool = this.drawTool;
                    this.selection = SelectionType.DateRange;
                }
                else
                {
                    drawTool = this.selectionTool;
                    this.selectedAppointment = appointmentAt;
                    this.selection = SelectionType.Appointment;
                    base.Invalidate();
                }
                if (this.activeTool != null)
                {
                    this.activeTool.MouseDown(e);
                }
                if ((this.activeTool != drawTool) && (drawTool != null))
                {
                    drawTool.Reset();
                    drawTool.MouseDown(e);
                }
                this.activeTool = drawTool;
                base.OnMouseDown(e);
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (this.activeTool != null)
            {
                this.activeTool.MouseMove(e);
            }
            base.OnMouseMove(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (this.activeTool != null)
            {
                this.activeTool.MouseUp(e);
            }
            base.OnMouseUp(e);
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            base.OnMouseWheel(e);
            if (e.Delta < 0)
            {
                this.ScrollMe(true);
            }
            else
            {
                this.ScrollMe(false);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            ResolveAppointmentsEventArgs args = new ResolveAppointmentsEventArgs(this.StartDate, this.StartDate.AddDays((double) this.daysToShow));
            this.OnResolveAppointments(args);
            using (SolidBrush brush = new SolidBrush(this.renderer.BackColor))
            {
                e.Graphics.FillRectangle(brush, base.ClientRectangle);
            }
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            Rectangle rectangle = new Rectangle(0, 0, base.Width - this.scrollbar.Width, base.Height);
            Rectangle rect = rectangle;
            rect.X += this.hourLabelWidth + this.hourLabelIndent;
            rect.Y += this.HeaderHeight;
            rect.Width -= this.hourLabelWidth + this.hourLabelIndent;
            if (e.ClipRectangle.IntersectsWith(rect))
            {
                this.DrawDays(e, rect);
            }
            Rectangle rectangle3 = rectangle;
            rectangle3.Y += this.HeaderHeight;
            this.DrawHourLabels(e, rectangle3);
            Rectangle rectangle4 = rectangle;
            rectangle4.X += this.hourLabelWidth + this.hourLabelIndent;
            rectangle4.Width -= this.hourLabelWidth + this.hourLabelIndent;
            rectangle4.Height = this.dayHeadersHeight;
            if (e.ClipRectangle.IntersectsWith(rectangle4))
            {
                this.DrawDayHeaders(e, rectangle4);
            }
            Rectangle rectangle5 = rectangle;
            if (!this.AllowScroll)
            {
                rectangle5.X = (rectangle4.Width + this.hourLabelWidth) + this.hourLabelIndent;
                rectangle5.Width = this.scrollbar.Width;
                using (SolidBrush brush2 = new SolidBrush(this.renderer.BackColor))
                {
                    e.Graphics.FillRectangle(brush2, rectangle5);
                }
            }
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
        }

        private void OnRendererChanged()
        {
            this.Font = this.renderer.BaseFont;
            base.Invalidate();
        }

        protected virtual void OnResolveAppointments(ResolveAppointmentsEventArgs args)
        {
            if (this.ResolveAppointments != null)
            {
                this.ResolveAppointments(this, args);
            }
            this.allDayEventsHeaderHeight = 0;
            this.cachedAppointments.Clear();
            if ((this.selectedAppointmentIsNew && (this.selectedAppointment != null)) && ((this.selectedAppointment.StartDate > args.StartDate) && (this.selectedAppointment.StartDate < args.EndDate)))
            {
                args.Appointments.Add(this.selectedAppointment);
            }
            foreach (Appointment appointment in args.Appointments)
            {
                int day = -1;
                if ((appointment.StartDate.Day == appointment.EndDate.Day) && !appointment.AllDayEvent)
                {
                    day = appointment.StartDate.Day;
                }
                else
                {
                    day = -1;
                }
                AppointmentList list = (AppointmentList) this.cachedAppointments[day];
                if (list == null)
                {
                    list = new AppointmentList();
                    this.cachedAppointments[day] = list;
                }
                list.Add(appointment);
            }
        }

        protected virtual void OnStartDateChanged()
        {
            this.startDate = this.startDate.Date;
            this.selectedAppointment = null;
            this.selectedAppointmentIsNew = false;
            this.selection = SelectionType.DateRange;
            base.Invalidate();
        }

        protected virtual void OnStartHourChanged()
        {
            if (((this.startHour * 2) * this.halfHourHeight) > this.scrollbar.Maximum)
            {
                this.scrollbar.Value = this.scrollbar.Maximum;
            }
            else
            {
                this.scrollbar.Value = (this.startHour * 2) * this.halfHourHeight;
            }
            base.Invalidate();
        }

        internal void RaiseAppointmentMove(AppointmentEventArgs e)
        {
            if (this.AppointmentMove != null)
            {
                this.AppointmentMove(this, e);
            }
        }

        internal void RaiseNewAppointment()
        {
            NewAppointmentEventArgs args = new NewAppointmentEventArgs(this.selectedAppointment.Title, this.selectedAppointment.StartDate, this.selectedAppointment.EndDate);
            if (this.NewAppointment != null)
            {
                this.NewAppointment(this, args);
            }
            this.selectedAppointment = null;
            this.selectedAppointmentIsNew = false;
            base.Invalidate();
        }

        internal void RaiseSelectionChanged(EventArgs e)
        {
            if (this.SelectionChanged != null)
            {
                this.SelectionChanged(this, e);
            }
        }

        private void scrollbar_Scroll(object sender, ScrollEventArgs e)
        {
            base.Invalidate();
            if (this.editbox.Visible)
            {
                this.editbox.Top += e.OldValue - e.NewValue;
            }
        }

        public void ScrollMe(bool down)
        {
            if (this.AllowScroll)
            {
                int num;
                if (down)
                {
                    num = this.scrollbar.Value + this.scrollbar.SmallChange;
                    if (num < this.scrollbar.Maximum)
                    {
                        this.scrollbar.Value = num;
                    }
                    else
                    {
                        this.scrollbar.Value = this.scrollbar.Maximum;
                    }
                }
                else
                {
                    num = this.scrollbar.Value - this.scrollbar.SmallChange;
                    if (num > this.scrollbar.Minimum)
                    {
                        this.scrollbar.Value = num;
                    }
                    else
                    {
                        this.scrollbar.Value = this.scrollbar.Minimum;
                    }
                }
                base.Invalidate();
            }
        }

        private void selectionTool_Complete(object sender, EventArgs e)
        {
            if (this.selectedAppointment != null)
            {
                //ThreadPool.QueueUserWorkItem(new WaitCallback(this.EnterEditMode));
            }
        }

        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            base.SetBoundsCore(x, y, width, height, specified);
            this.AdjustScrollbar();
        }

        public void StartEditing()
        {
            if (!this.selectedAppointment.Locked && this.appointmentViews.ContainsKey(this.selectedAppointment))
            {
                Rectangle rectangle = this.appointmentViews[this.selectedAppointment].Rectangle;
                rectangle.Inflate(-3, -3);
                rectangle.X += this.appointmentGripWidth - 2;
                rectangle.Width -= this.appointmentGripWidth - 5;
                this.editbox.Bounds = rectangle;
                this.editbox.Text = this.selectedAppointment.Title;
                this.editbox.Visible = true;
                this.editbox.SelectionStart = this.editbox.Text.Length;
                this.editbox.SelectionLength = 0;
                this.editbox.Focus();
            }
        }

        private void UpdateWorkingHours()
        {
            this.workStart = new DateTime(1, 1, 1, this.workingHourStart, this.workingMinuteStart, 0);
            this.workEnd = new DateTime(1, 1, 1, this.workingHourEnd, this.workingMinuteEnd, 0);
            base.Invalidate();
        }

        [Browsable(false)]
        public ITool ActiveTool
        {
            get
            {
                return this.activeTool;
            }
            set
            {
                this.activeTool = value;
            }
        }

        [DefaultValue(true)]
        public bool AllowInplaceEditing
        {
            get
            {
                return this.allowInplaceEditing;
            }
            set
            {
                this.allowInplaceEditing = value;
            }
        }

        [DefaultValue(true)]
        public bool AllowNew
        {
            get
            {
                return this.allowNew;
            }
            set
            {
                this.allowNew = value;
            }
        }

        [DefaultValue(true)]
        public bool AllowScroll
        {
            get
            {
                return this.allowScroll;
            }
            set
            {
                this.allowScroll = value;
                this.OnAllowScrollChanged();
            }
        }

        public bool AmPmDisplay
        {
            get
            {
                return this.ampmdisplay;
            }
            set
            {
                this.ampmdisplay = value;
                this.OnAmPmDisplayChanged();
            }
        }

        public AppHeightDrawMode AppHeightMode
        {
            get
            {
                return this.appHeightMode;
            }
            set
            {
                this.appHeightMode = value;
            }
        }

        [Browsable(false)]
        public bool CurrentlyEditing
        {
            get
            {
                return this.editbox.Visible;
            }
        }

        [DefaultValue(1)]
        public int DaysToShow
        {
            get
            {
                return this.daysToShow;
            }
            set
            {
                this.daysToShow = value;
                this.OnDaysToShowChanged();
            }
        }

        public bool DrawAllAppBorder
        {
            get
            {
                return this.drawAllAppBorder;
            }
            set
            {
                this.drawAllAppBorder = value;
                this.OnDrawAllAppBorderChanged();
            }
        }

        [DefaultValue(0x12)]
        public int HalfHourHeight
        {
            get
            {
                return this.halfHourHeight;
            }
            set
            {
                this.halfHourHeight = value;
                this.OnHalfHourHeightChanged();
            }
        }

        private int HeaderHeight
        {
            get
            {
                return (this.dayHeadersHeight + this.allDayEventsHeaderHeight);
            }
        }

        public bool MinHalfHourApp
        {
            get
            {
                return this.minHalfHourApp;
            }
            set
            {
                this.minHalfHourApp = value;
                base.Invalidate();
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Browsable(false)]
        public AbstractRenderer Renderer
        {
            get
            {
                return this.renderer;
            }
            set
            {
                this.renderer = value;
                this.OnRendererChanged();
            }
        }

        [Browsable(false)]
        public Appointment SelectedAppointment
        {
            get
            {
                return this.selectedAppointment;
            }
        }

        public bool SelectedAppointmentIsNew
        {
            get
            {
                return this.selectedAppointmentIsNew;
            }
        }

        [Browsable(false)]
        public SelectionType Selection
        {
            get
            {
                return this.selection;
            }
        }

        public DateTime SelectionEnd
        {
            get
            {
                return this.selectionEnd;
            }
            set
            {
                this.selectionEnd = value;
            }
        }

        public int NumberWorkingDay
        {
            get { return numberWorkingDay; }
            set 
            {
                if (value < 5)
                    numberWorkingDay = 5;
                else if (value > 7)
                    numberWorkingDay = 7;
                else
                    numberWorkingDay = value;

                Invalidate();
            }
        }

        public DateTime SelectionStart
        {
            get
            {
                return this.selectionStart;
            }
            set
            {
                this.selectionStart = value;
            }
        }

        public DateTime StartDate
        {
            get
            {
                return this.startDate;
            }
            set
            {
                this.startDate = value;
                this.OnStartDateChanged();
            }
        }

        [DefaultValue(8)]
        public int StartHour
        {
            get
            {
                return this.startHour;
            }
            set
            {
                this.startHour = value;
                this.OnStartHourChanged();
            }
        }

        [DefaultValue(0x12)]
        public int WorkingHourEnd
        {
            get
            {
                return this.workingHourEnd;
            }
            set
            {
                this.workingHourEnd = value;
                this.UpdateWorkingHours();
            }
        }

        [DefaultValue(8)]
        public int WorkingHourStart
        {
            get
            {
                return this.workingHourStart;
            }
            set
            {
                this.workingHourStart = value;
                this.UpdateWorkingHours();
            }
        }

        [DefaultValue(30)]
        public int WorkingMinuteEnd
        {
            get
            {
                return this.workingMinuteEnd;
            }
            set
            {
                this.workingMinuteEnd = value;
                this.UpdateWorkingHours();
            }
        }

        [DefaultValue(30)]
        public int WorkingMinuteStart
        {
            get
            {
                return this.workingMinuteStart;
            }
            set
            {
                this.workingMinuteStart = value;
                this.UpdateWorkingHours();
            }
        }

        public enum AppHeightDrawMode
        {
            TrueHeightAll,
            FullHalfHourBlocksAll,
            EndHalfHourBlocksAll,
            FullHalfHourBlocksShort,
            EndHalfHourBlocksShort
        }

        private class AppointmentList : List<Appointment>
        {
        }

        internal class AppointmentView
        {
            public Appointment Appointment;
            public System.Drawing.Rectangle Rectangle;
        }

        private class HalfHourLayout
        {
            public Appointment[] Appointments;
            public int Count;
            public List<string> Groups;
        }

        private delegate void StartEditModeDelegate(object state);
    }
}
